<template>
  <page-meta :root-font-size="rootFontSize() + 'px'"></page-meta>

  <view class="page-container" v-show="delayShow">
    <customHeader title="角色扮演" />

    <view class="status-line" v-if="!isComplete">
      <view class="status-active" :style="{ width: `${progress}%` }"></view>
    </view>

    <view class="container" :style="{ top: height }">
      <view class="speaking-container" v-if="!isComplete">
        <text class="tip" :style="{ opacity: isStartAnimation ? 0 : 1 }">朗读句子，完成角色对话</text>
        <view class="role-container-one"
          :class="[isStartAnimation ? 'role-container-one-appear' : '', myHeadOpacity == 1 ? 'role-speak' : 'role-silence']">
          <image v-if="isStartAnimation" class="role-tip" :class="[isStartAnimation ? 'role-tip-appear' : '']"
            src="https://rwstatic.tentons.cn/web/Lesson/images/roleplay-tip.png" />
          <image v-if="!isStartAnimation && isMine" class="role-speak-background"
            src="https://rwstatic.tentons.cn/web/Lesson/images/roleplay-speak-background.png">
          </image>
          <image class="role-icon" :src="env.prefixUrl + pageData?.userImg"></image>
          <image v-if="isMine && isSpeaking" class="role-speak-icon"
            src="https://rwstatic.tentons.cn/web/Lesson/images/roleplay-speek.png"></image>
        </view>
        <view class="role-container-two"
          :class="[isStartAnimation ? 'role-container-two-appear' : '', otherHeadOpacity == 1 ? 'role-speak' : 'role-silence']">
          <image v-if="!isStartAnimation && !isMine" class="role-speak-background"
            src="https://rwstatic.tentons.cn/web/Lesson/images/roleplay-speak-background.png">
          </image>
          <image class="role-icon" :src="env.prefixUrl + pageData?.systemImg"></image>
        </view>
        <view v-if="isMine && !isStartAnimation" class="role-chat-container">
          <sentence class="role-chat-content" :sentence="markCurrentSentence" />
        </view>
        <record-sound v-if="isMine" title="朗读句子" @on-upload-success="onRecorderSuccess"></record-sound>
      </view>
      <view class="complete-container" v-if="isComplete">
        <view class="messages-container">
          <view v-for="(item, index) in pageData?.rolePlay"
            :class="[item.role === 0 ? 'one-message-container' : 'two-message-container']"
            :style="{ animationDelay: `${0.2 + index * 0.1}s` }">
            <image v-if="item.role === 0" class="chat-head" :src="env.prefixUrl + pageData?.userImg" />
            <view class="chat-container">
              <sentence class="chat-content" :sentence="handleSetMark(item.sentences_bh)" />
            </view>
            <image v-if="item.role === 1" class="chat-head" :src="env.prefixUrl + pageData?.systemImg" />
          </view>
          <view class="footer"></view>
        </view>
        <button class="continue" @click="doContinue">继续学习</button>
      </view>
    </view>
  </view>
  <CwCommon />
</template>

<script setup lang="ts">
import { onBeforeUnmount, ref } from "vue";
import { rootFontSize, util } from "@/utils/util";
import customHeader from "@/components/customHeader.vue";
import { computed } from "vue";
import API from "@/api";
import env from "@/config/env";
import { onLoad, onUnload } from "@dcloudio/uni-app";
import { AudioManager } from "@/utils/AudioManager";
import recordSound from "@/components/recordSound.vue";
import sentence from "@/components/sentence.vue";
import type { IUploadSuccessInfo } from "@/components/recordSound.vue";
import { startEvaluating } from "@/utils/chivox";
import type { ILessonResult } from "@/pages/lowPricedCourse/trialCourseHome/courseList/index.vue";
import { useDelayShow } from "@/hooks/useDelayShow";

const { delayShow } = useDelayShow();

export interface IRolePlayResult extends Omit<ILessonResult, "data"> {
  data: IResult;
}

export interface IResult {
  userImg: string;
  systemImg: string;
  toCompPage: number;
  rolePlay: IMessage[];
  currentMessageIndex: number;
  lastUserMessageIndex: number;
}

interface IMessage {
  role_play_id: number;
  role: number; // 0： 用户读 1： 系统读
  sentences: string;
  us_voice: string;
  uk_voice: string;
  user_voice?: string;
  score: number;
  sentences_bh: string; //标红字符串
  analysis?: string; //评测结果
}

const height = ref(getApp().globalData!.pageTop);
const fs = uni.getFileSystemManager();

const pageData = ref<IResult | null>(null);
const isSpeaking = ref(false);
const isStartAnimation = ref(true);
const isSynthesis = ref(true); // 是否是口语综合
const isReStart = ref(false); // 再次重新开始
const currentMessageIndex = ref(-1);
const isComplete = ref(false);
var sectionId: number | null = null;
var isRelearn = false;
var lastUserMessageIndex = -1;

onLoad(async (option: any) => {
  sectionId = option.section_id;
  let data = JSON.parse(decodeURIComponent(option.data)) as IRolePlayResult;
  isRelearn = data.isRelearn;
  isReStart.value = option.isReStart === "true";
  if (option.isSynthesis) {
    isSynthesis.value = option.isSynthesis === "true";
  }

  pageData.value = data.data;
  currentMessageIndex.value = data.data.currentMessageIndex;
  lastUserMessageIndex = data.data.lastUserMessageIndex;

  setTimeout(() => {
    isStartAnimation.value = false;
    checkAndPlaySystemVoice();
  }, 3000);
});

onUnload(() => {
  pageData.value = null;
});

const progress = computed(() => {
  if (!pageData.value) {
    return 0;
  }
  return (currentMessageIndex.value / pageData.value.rolePlay.length) * 100;
});

const checkAndPlaySystemVoice = () => {
  if (isMine.value) {
    return;
  }
  AudioManager.getInstance().play({
    src: env.prefixUrl + currentMessage.value?.us_voice,
    onVoiceEnded: () => {
      checkIsComplete();
    },
  });
};

const checkIsComplete = () => {
  if (currentMessageIndex.value + 1 <= pageData.value!.rolePlay.length - 1) {
    currentMessageIndex.value++;
    checkAndPlaySystemVoice();
    return;
  }

  isComplete.value = true;

  API.rolePlayComplete({ section_id: sectionId });

  return true;
};

const currentMessage = computed(() => {
  return pageData.value?.rolePlay[currentMessageIndex.value];
});

const markCurrentSentence = computed(() => {
  return {
    mark: {
      begin: "<b>",
      end: "</b>",
    },
    content: pageData.value!.rolePlay[currentMessageIndex.value].sentences_bh,
  }
})

const isMine = computed(() => {
  if (!currentMessage.value) {
    return true;
  }
  return currentMessage.value!.role === 0;
});

const myHeadOpacity = computed(() => {
  if (isStartAnimation.value) {
    return 1;
  }
  return isMine.value ? 1 : 0.5;
});

const otherHeadOpacity = computed(() => {
  if (isStartAnimation.value) {
    return 1;
  }
  return isMine.value ? 0.5 : 1;
});

const handleSetMark = (sentence: string) => {
  return {
    mark: {
      begin: "<b>",
      end: "</b>",
    },
    content: sentence,
  }
}

const onRecorderSuccess = (info: IUploadSuccessInfo) => {
  if (!info.ossFilePath) {
    return;
  }
  currentMessage.value!.user_voice = info.ossFilePath;
  util.showLoading();
  fs.readFile({
    filePath: info.localFilePath,
    success(res) {
      startEvaluating({
        evaluatingInfo: { sentence: currentMessage.value!.sentences },
        audioBuffer: res.data as ArrayBuffer,
        onSuccess: (res) => {
          console.log(JSON.stringify(res));
          util.hideLoading();
          currentMessage.value!.analysis = JSON.stringify(res);
          reportCurrentMessage();
        },
        onError: (errMsg) => {
          console.log(errMsg);

          util.showDialogue(errMsg);
          util.hideLoading();
        },
      });
    },
    fail(res) {
      util.showDialogue("找不到音频文件");
      util.hideLoading();
    },
  });
};

const reportCurrentMessage = async () => {
  if (!currentMessage.value) {
    return;
  }
  if (isRelearn && currentMessageIndex.value < lastUserMessageIndex) {
    console.log(isRelearn);
    checkIsComplete();
    return;
  }

  const params = {} as any;
  params["section_id"] = sectionId;
  const messages = [] as any;

  if (!isRelearn) {
    const message = currentMessage.value!;
    messages.push({ role_play_id: message.role_play_id, user_voice: message.user_voice, analysis: message.analysis });
  } else {
    pageData.value!.rolePlay.forEach((message) => {
      if (message.role === 0) {
        messages.push({ role_play_id: message.role_play_id, user_voice: message.user_voice, analysis: message.analysis });
      }
    });
  }
  params["role_play"] = messages;
  try {
    const data = await API.rolePlayReport(params);
    console.log(JSON.stringify(data));
    checkIsComplete();
  } catch { }
};

const doContinue = () => {
  let temp = {};
  if (isReStart.value) {
    temp = {
      isRelearn: true,
    }
  }

  uni.redirectTo({
    url: `/pages/lowPricedCourse/situationalDialog/scoreOverall/index?section_id=${sectionId}&headerTitle=角色扮演&data=${encodeURIComponent(JSON.stringify(temp))}&type=3&isReStart=${isReStart.value}&isSynthesis=${isSynthesis.value}`,
  });
};

onBeforeUnmount(() => {
  AudioManager.getInstance().stop();
})
</script>

<style scoped lang="scss">
.page-container {
  width: 100vw;
  height: 100vh;
  background-color: #ffffff;

  .status-line {
    width: 100%;
    height: 0.5rem;
    border: 0.5px solid rgba(0, 0, 0, 0.2);

    .status-active {
      height: 100%;
      transition: width 0.3s ease;
      border-top-right-radius: 0.45rem;
      border-bottom-right-radius: 0.45rem;
      background-color: #ffd6db;
    }
  }

  .container {
    position: absolute;
    width: 37.5rem;
    top: 6rem;
    bottom: 0;
    left: 50%;
    transform: translateX(-50%);

    .speaking-container {
      .tip {
        position: absolute;
        left: 3rem;
        top: 3.1rem;
        font-size: 1.6rem;
        font-family: xiaolai;
        color: $uni-text-color;
      }

      .role-container-one {
        position: absolute;
        left: 3rem;
        top: 7.9rem;
        width: 8rem;
        height: 8rem;

        .role-tip {
          position: absolute;
          top: -5.6rem;
          width: 11rem;
          height: 4.6rem;
          left: 50%;
          transform: translateX(-50%);
        }

        .role-tip-appear {
          animation:
            role-tip-appear 0.3s linear 0.85s,
            role-tip-disappear 0.3s linear 2.05s;
          animation-fill-mode: both;
        }

        .role-speak-background {
          position: absolute;
          width: 11.2rem;
          height: 11.2rem;
          left: 50%;
          top: 50%;
          transform: translate3d(-50%, -50%, 0);
        }

        .role-icon {
          position: absolute;
          width: 100%;
          height: 100%;
          border-radius: 50%;
          border: 0.2rem solid #d8ab61;
          box-sizing: border-box;
        }

        .role-speak-icon {
          position: absolute;
          width: 2rem;
          height: 2rem;
          left: 5.8rem;
          top: 5.8rem;
        }
      }

      .role-container-one-appear {
        animation:
          role-container-one-appear 0.3s linear 0.2s,
          role-container-one-move 0.5s linear 1.45s;
        animation-fill-mode: both;
      }

      .role-container-two {
        position: absolute;
        right: 3rem;
        top: 7.9rem;
        width: 8rem;
        height: 8rem;

        .role-speak-background {
          position: absolute;
          width: 11.2rem;
          height: 11.2rem;
          left: 50%;
          top: 50%;
          transform: translate3d(-50%, -50%, 0);
        }

        .role-icon {
          position: absolute;
          width: 100%;
          height: 100%;
          border-radius: 50%;
          border: 0.2rem solid #d8ab61;
          box-sizing: border-box;
        }
      }

      .role-container-two-appear {
        animation:
          role-container-two-appear 0.3s linear 0.3s,
          role-container-two-move 0.5s linear 1.45s;
        animation-fill-mode: both;
      }

      .role-chat-container {
        position: absolute;
        top: 18.1rem;
        left: 3rem;
        right: 3rem;
        border-image-slice: 57 27 35 168 fill;
        border-image-width: 1.9rem 0.9rem 1.13rem 5.6rem;
        border-image-outset: 0px 0px 0px 0px;
        border-image-repeat: stretch stretch;
        border-image-source: url("https://rwstatic.tentons.cn/web/Lesson/images/roleplay-chat-background.png");
        border-style: solid;
        display: inline-block;
        padding: 2rem 2rem 1.5rem 2rem;

        animation: role-chat-container-appear 0.3s linear;

        .role-chat-content {
          font-family: xiaolai;
          font-size: 1.5rem;
          color: $uni-text-color;
        }
      }

      .record {
        position: absolute;
        bottom: 4.7rem;
        width: 15rem;
        height: 5rem;
        left: 50%;
        transform: translateX(-50%);
      }
    }

    .complete-container {
      width: 100%;
      height: 100%;

      .messages-container {
        position: absolute;
        display: flex;
        flex-direction: column;
        width: 100%;
        overflow: auto;
        height: 100%;

        .one-message-container {
          margin-top: 1.6rem;
          display: flex;
          // align-items: center;
          width: 100%;
          /* 视图的固定宽度 */
          animation: message-appear 0.3s ease-in-out;
          animation-fill-mode: both;

          .chat-head {
            // position: absolute;
            margin-left: 2rem;
            margin-right: 0.8rem;
            width: 4rem;
            height: 4rem;
            border-radius: 50%;
            border: 0.12rem solid #d8ab61;
            box-sizing: border-box;
          }

          .chat-container {
            // position: absolute;
            top: 0;
            max-width: 20.5rem;
            border-image-slice: 87 39 36 57 fill;
            border-image-width: 2.9rem 1.3rem 1.2rem 1.9rem;
            border-image-outset: 0px 0px 0px 0px;
            border-image-repeat: stretch stretch;
            border-image-source: url("https://rwstatic.tentons.cn/web/Lesson/images/roleplay-mychat-background.png");
            border-style: solid;
            display: inline-block;
            padding: 1.1rem 1.46rem 1.1rem 2.1rem;

            .chat-content {
              font-size: 1.6rem;
              color: $uni-text-color;
            }
          }
        }

        .two-message-container {
          margin-top: 1.6rem;
          display: flex;
          // align-items: center;
          width: 100%;
          /* 视图的固定宽度 */
          animation: message-appear 0.3s ease-in-out;
          animation-fill-mode: both;
          justify-content: flex-end;

          // flex-direction: row-reverse;
          .chat-head {
            // position: absolute;
            margin-right: 2rem;
            margin-left: 0.8rem;
            width: 4rem;
            height: 4rem;
            border-radius: 50%;
            border: 0.12rem solid #d8ab61;
            box-sizing: border-box;
          }

          .chat-container {
            // position: absolute;
            top: 0;
            max-width: calc(22.5rem - 2.1rem - 1.46rem);
            border-image-slice: 87 57 36 39 fill;
            border-image-width: 2.9rem 1.9rem 1.2rem 1.3rem;
            border-image-outset: 0px 0px 0px 0px;
            border-image-repeat: stretch stretch;
            border-image-source: url("https://rwstatic.tentons.cn/web/Lesson/images/roleplay-otherchat-background.png");
            border-style: solid;
            display: inline-block;
            padding: 1.1rem 2.1rem 1.1rem 1.46rem;

            .chat-content {
              font-size: 1.6rem;
              color: $uni-text-color;
            }
          }
        }

        .footer {
          height: 10rem;
          margin-top: 0rem;
          width: 100%;
          flex-shrink: 0;
        }
      }

      .continue {
        position: absolute;
        bottom: 2.5rem;
        left: 50%;
        transform: translateX(-50%);
        display: flex;
        align-items: center;
        justify-content: center;
        width: 31.5rem;
        height: 5rem;
        margin: 0;
        font-family: xiaolai;
        font-size: 1.7rem;
        border-radius: 1rem;
        color: $uni-text-color;
        border: 2px solid $uni-btn-border;
        background-color: #c5ce71;
      }
    }
  }
}

.role-speak {
  animation: role-speak 0.3s linear;
  animation-fill-mode: both;
}

.role-silence {
  animation: role-silence 0.3s linear;
  animation-fill-mode: both;
}

@keyframes role-container-one-appear {
  from {
    top: 22.7rem;
    left: 5rem;
    width: 11rem;
    height: 11rem;
    transform: scale(0.5);
    opacity: 0;
  }

  to {
    top: 22.7rem;
    left: 5rem;
    width: 11rem;
    height: 11rem;
    transform: scale(1);
    opacity: 1;
  }
}

@keyframes role-container-one-move {
  from {
    top: 22.7rem;
    left: 5rem;
    width: 11rem;
    height: 11rem;
  }

  to {
    left: 3rem;
    top: 7.9rem;
    width: 8rem;
    height: 8rem;
  }
}

@keyframes role-container-two-appear {
  from {
    top: 22.7rem;
    right: 5rem;
    width: 11rem;
    height: 11rem;
    transform: scale(0.5);
    opacity: 0;
  }

  to {
    top: 22.7rem;
    right: 5rem;
    width: 11rem;
    height: 11rem;
    transform: scale(1);
    opacity: 1;
  }
}

@keyframes role-container-two-move {
  from {
    top: 22.7rem;
    right: 5rem;
    width: 11rem;
    height: 11rem;
  }

  to {
    right: 3rem;
    top: 7.9rem;
    width: 8rem;
    height: 8rem;
  }
}

@keyframes role-tip-appear {
  from {
    transform: translateX(-50%) translateY(-3rem) scale(0.8);
    opacity: 0;
  }

  to {
    transform: translateX(-50%);
    opacity: 1;
  }
}

@keyframes role-tip-disappear {
  to {
    transform: translateX(-50%);
    opacity: 0;
  }
}

@keyframes role-speak {
  to {
    opacity: 1;
  }
}

@keyframes role-silence {
  to {
    opacity: 0.5;
  }
}

@keyframes role-chat-container-appear {
  from {
    transform: translateY(3rem) scale(0.8);
    opacity: 0;
  }

  to {
    transform: translateY(0) scale(1);
    opacity: 1;
  }
}

@keyframes message-appear {
  from {
    transform: translateY(3rem);
    opacity: 0;
  }

  to {
    transform: translateY(0);
    opacity: 1;
  }
}
</style>
